//////////////////////////////////////////////////////////////////////////////////
//	Copyright 2011 by Yosef Grabivker, ryuho@homenetworksoft.com
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//////////////////////////////////////////////////////////////////////////////////

#include "rtping.h"
#include "rtsocket.h"

#ifdef _WINDOWS
#include <winsock2.h>
#include <iphlpapi.h>
#include <icmpapi.h>
#include <stdio.h>
#include <Ws2tcpip.h>
#include <mswsock.h>

#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")

#endif

CRTPing::CRTPing(void)
{
}

CRTPing::~CRTPing(void)
{
}

void CRTPing::operator()(const wxString& strHost, size_t stPingCnt, PINGRESULT& result )
{
	if ( !stPingCnt )THROW_EXC(cERParam);

	size_t stMin(-1); 
	size_t stMax(0);
	bool bPingResult(false);

	while( stPingCnt-- )
	{
		size_t stTime =  0;
		
		bPingResult = DoPing( strHost, stTime );

		if (stTime>stMax) stMax = stTime;
		if (stTime<stMin) stMin = stTime;
	}

	result.bDispatched = false;
	result.bPingResult = bPingResult;
	result.stPingJitter = bPingResult?(stMax-stMin):0;
	result.stPingTime = bPingResult?((stMax+stMin)/2):0;
	result.tEvent = time(NULL);
 }

//////////////////////////////////////////////////////////////////////////
//DoPing
#ifdef _WINDOWS
bool CRTPing::DoPing(const wxString& strHost, size_t& stTimeMS )
{
	bool bRes(false);

	HANDLE hIcmpFile;
	unsigned long ipaddr = INADDR_NONE;
	DWORD dwRetVal = 0;
	char SendData[32] = "RouterCommander";

	LPVOID ReplyBuffer = NULL;
	DWORD ReplySize = 0;

	struct addrinfo *aiList = CRTSocket::GetAddress(strHost.ToAscii(), 999);

	if (!aiList)
	{
		stTimeMS = 0;
		return false;
	}

	if ( aiList->ai_family != AF_INET )
	{
		THROW_EXC(cERParam);
	}

	hIcmpFile = IcmpCreateFile();

	if (hIcmpFile == INVALID_HANDLE_VALUE)
	{
		THROW_EXC(cERSysCall);
	}

	ReplySize = sizeof(ICMP_ECHO_REPLY) + sizeof(SendData);
	ReplyBuffer = (VOID*) malloc(ReplySize);

	if (!ReplyBuffer)
	{
		IcmpCloseHandle(hIcmpFile);
		THROW_EXC(cERNoFreeMem);
	}

	
	ipaddr = ((sockaddr_in *)aiList->ai_addr)->sin_addr.s_addr;

	dwRetVal = IcmpSendEcho(hIcmpFile, ipaddr, SendData, sizeof(SendData), 
			NULL, ReplyBuffer, ReplySize, 1000);
	
	if (dwRetVal != 0)
	{
		PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY)ReplyBuffer;

		stTimeMS = pEchoReply->RoundTripTime;
		bRes = IP_SUCCESS==pEchoReply->Status;
	}

	IcmpCloseHandle(hIcmpFile);
	free(ReplyBuffer);

	return bRes;
}

#endif